#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <sstream>
#include <istream>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>

//HQ add SNMP class
#include <net-snmp/net-snmp-config.h> //*****need to be changed in linux *******
#include <net-snmp/net-snmp-includes.h>//*****need to be changed in linux *******

//ASC INTERSECTION MIB
#define RED_GROUP "1.3.6.1.4.1.1206.4.2.1.1.4.1.2.1"                     //Object
#define YELLOW_GROUP "1.3.6.1.4.1.1206.4.2.1.1.4.1.3.1"
#define GREEN_GROUP "1.3.6.1.4.1.1206.4.2.1.1.4.1.4.1"
#define DONOTWALK_GROUP "1.3.6.1.4.1.1206.4.2.1.1.4.1.5.1"
#define PEDCLEAR_GROUP "1.3.6.1.4.1.1206.4.2.1.1.4.1.6.1"
#define WALK_GROUP "1.3.6.1.4.1.1206.4.2.1.1.4.1.7.1"
#define PREEMPTOR1 "1.3.6.1.4.1.1206.4.2.1.6.3.1.2.1"
#define PREEMPTOR2 "1.3.6.1.4.1.1206.4.2.1.6.3.1.2.2"
#define PREEMPTOR3 "1.3.6.1.4.1.1206.4.2.1.6.3.1.2.3"
#define PREEMPTOR4 "1.3.6.1.4.1.1206.4.2.1.6.3.1.2.4"
//Phase control
#define MIB_PHASE_HOLD "1.3.6.1.4.1.1206.4.2.1.1.5.1.4.1"
#define MIB_PHASE_FORCEOFF "1.3.6.1.4.1.1206.4.2.1.1.5.1.5.1"
#define MIB_PHASE_OMIT "1.3.6.1.4.1.1206.4.2.1.1.5.1.2.1"


//RAMP METER MIB
#define	NUMBER_METEREDLANES "1.3.6.1.4.1.1206.4.2.2.3.1.2"
#define LANE1_MODE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.1.1"
#define LANE2_MODE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.1.2"
#define LANE3_MODE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.1.3"
#define LANE1_MANUALACTION "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.2.1"
#define LANE2_MANUALACTION "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.2.2"
#define LANE3_MANUALACTION "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.2.3"
#define LANE1_MANUALRATE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.4.1"
#define LANE2_MANUALRATE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.4.2"
#define LANE3_MANUALRATE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.4.3"
#define LANE1_DEMANDMODE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.18.1"
#define LANE2_DEMANDMODE "1.3.6.1.4.1.1206.4.2.2.3.1.7.1.18.2"
//emgerence green, set manual action to 5. undo, set to 3
//keep Red, set demand mode to 3. undo, set to 1
#define MAX_ITEMS 20

#define numPhases 8
//Ramp meter ip port
const char *RMip = "150.135.152.24";
const char *RMport = "161";
//intersection asc controller ip port
const char *INTip = "150.135.152.23";
const char *INTport = "501";


// for socket communication with obu
#define PORT 15020 //PREEMPTION port
#define BROADCAST_ADDR "192.168.255.255"
#define RSU_ADDR "192.168.1.21"

//tell ramp or intersection
#define RAMP 0
#define INTERSECTION 1

//define the different phase control types
#define	PHASE_HOLD 0
#define PHASE_FORCEOFF 1
#define PHASE_OMIT 2


struct PHASE
{
	bool isRed;
	bool isGreen;
	bool isYellow;

};

PHASE vehiclePhases[numPhases];

//define log file name
char logfilename[256] = "/usr/local/bin/RSU_NTCIP_";

void IntersectionPhaseControl(int phase_control, int phaseNO);//Phase Control action set(ON=yes) or clear(ON=no) for intersection ASC controller
void IntersectionPhaseRead();//group=Red or Yellow or Green
void UpdateIntersectionStatus(int red, int yellow, int green);//update current intersection phase status
void PrintPhases(); //print phase status into log
void IntersectionPreempt(int NO, bool ON);

int outputlog(char *output);
void xTimeStamp( char * pc_TimeStamp_ );
int msleep(unsigned long milisec);

char * getBufferAsBinaryString(void* in)
{
	int pos=0;
	char result;
	char bitstring[16];
	memset(bitstring, 0, 16);
	unsigned int *input= (unsigned int *)in;
	for(int i=7;i>=0;i--)
	{
		//if (((*input >> i) & 1)) result = '1';
		//else result = '0';
		if (i>0)
		{
			if (((*input >> i) % 2)) result = '1';
			else result = '0';
		}
		else
		{
			if (((*input) % 2)) result = '1';
			else result = '0';
		}

		bitstring[pos] = result;
		pos++;
	}
	bitstring[pos] = '1';
	strcat(bitstring,"END");
	return bitstring;

}

void     xTimeStamp( char * pc_TimeStamp_ )
{
          struct tm  * ps_Time;
          time_t       i_CurrentTime;
          char         ac_TmpStr[256];

          i_CurrentTime =  time(NULL);
          ps_Time = localtime( &i_CurrentTime );

                      //year
          sprintf(ac_TmpStr, "%d", ps_Time->tm_year + 1900);
          strcpy(pc_TimeStamp_, ac_TmpStr);

                      //month
          sprintf(ac_TmpStr, "_%d", ps_Time->tm_mon + 1 );
          strcat(pc_TimeStamp_, ac_TmpStr);

                     //day
          sprintf(ac_TmpStr, "_%d", ps_Time->tm_mday );
          strcat(pc_TimeStamp_, ac_TmpStr);

                     //hour
          sprintf(ac_TmpStr, "_%d", ps_Time->tm_hour  );
          strcat(pc_TimeStamp_, ac_TmpStr);

                     //min
          sprintf(ac_TmpStr, "_%d", ps_Time->tm_min );
          strcat(pc_TimeStamp_, ac_TmpStr);

                     //sec
          sprintf(ac_TmpStr, "_%d", ps_Time->tm_sec );
          strcat(pc_TimeStamp_, ac_TmpStr);
}


int msleep(unsigned long milisec)
{
    struct timespec req={0};
    time_t sec=(int)(milisec/1000);
    milisec=milisec-(sec*1000);
    req.tv_sec=sec;
    req.tv_nsec=milisec*1000000L;
    while(nanosleep(&req,&req)==-1)
       continue;
    return 1;
}

int outputlog(char *output)
{
	FILE * stream = fopen( logfilename, "r" );
        fseek( stream, 0L, SEEK_END );
        long endPos = ftell( stream );
        fclose( stream );

	std::fstream fs;
        if (endPos <1000000)
		fs.open(logfilename, std::ios::out | std::ios::app);
	else
		fs.open(logfilename, std::ios::out | std::ios::trunc);
	if (!fs || !fs.good())
	{
		std::cout << "could not open file!\n";
		return -1;
	}
	fs << output << std::endl;

	if (fs.fail())
	{
		std::cout << "failed to append to file!\n";
		return -1;
	}


	return 1;
}

int main ( int argc, char* argv[] )
{
  	//define broadcast network vars
  	int sockfd;
  	int broadcast=1;
  	struct sockaddr_in recvaddr;
  	struct sockaddr_in sendaddr;
  	int numbytes;
  	char sendMSG[256] ="";
  	char recvbuff[256] = "";
  	int  recvbufflen = 256;
   	unsigned int type = 0;

	//------log file name with Time stamp---------------------------
	char timestamp[128];
	char tmp_log[64];
	xTimeStamp(timestamp);
	strcat(logfilename,timestamp);
	strcat(logfilename,".log");
	//------end log file name-----------------------------------

	std::fstream fs;
	fs.open(logfilename, std::ios::out | std::ios::trunc);

	while ( true )
	{
		sprintf(tmp_log,"1.Test phase hold control...\n");
		std::cout <<tmp_log;
		outputlog(tmp_log);
		IntersectionPhaseRead();
		PrintPhases();
		msleep(1000);

		//IntersectionPhaseControl(PHASE_HOLD, 2);
		//msleep(5000);


		//IntersectionPhaseControl(PHASE_HOLD, 1);

	}





}



void IntersectionPhaseControl(int phase_control, int phaseNO)
{
		char tmp_log[64];
		char tmp_int[16];
	   	netsnmp_session session, *ss;
		netsnmp_pdu *pdu;
		netsnmp_pdu *response;

		oid anOID[MAX_OID_LEN];
		size_t anOID_len;

		netsnmp_variable_list *vars;
		int status;
		int count=1;
		int  failures = 0;

		sprintf(tmp_int,"%d",phaseNO);

		/*
		* Initialize the SNMP library
		*/
		init_snmp("RSU");

		/*
		* Initialize a "session" that defines who we're going to talk to
		*/
		snmp_sess_init( &session );                   /* set up defaults */

		char ipwithport[64];
		strcpy(ipwithport,INTip);
		strcat(ipwithport,":");
		strcat(ipwithport,INTport);
		session.peername = strdup(ipwithport);

		/* set the SNMP version number */
		session.version = SNMP_VERSION_2c;

		/* set the SNMPv1 community name used for authentication */
		session.community = (u_char *)"public";
		session.community_len = strlen((const char *)session.community);

		SOCK_STARTUP;
		ss = snmp_open(&session);                     /* establish the session */

		if (!ss)
		{
			snmp_sess_perror("RSU", &session);
			SOCK_CLEANUP;
			exit(1);
		}

		/*
		* Create the PDU for the data for our request.
		*   1) We're going to SET the system.sysDescr.0 node.
		*/
		pdu = snmp_pdu_create(SNMP_MSG_SET);
		anOID_len = MAX_OID_LEN;
		if (PHASE_HOLD==phase_control)
		{
			if (!snmp_parse_oid(MIB_PHASE_HOLD, anOID, &anOID_len))
			{
				snmp_perror(MIB_PHASE_HOLD);
				failures++;
			 }

			 sprintf(tmp_log,"Send command to ASC controller: Phase hold control!\n");
			 std::cout <<tmp_log;
			 outputlog(tmp_log);

		}
		else if (PHASE_FORCEOFF==phase_control)
		{
			if (!snmp_parse_oid(MIB_PHASE_FORCEOFF, anOID, &anOID_len))
			{
				snmp_perror(MIB_PHASE_FORCEOFF);
				failures++;
			 }
			 sprintf(tmp_log,"Send command to ASC controller: Phase forceoff control!\n");
 			 std::cout <<tmp_log;
			 outputlog(tmp_log);

		}
		else if (PHASE_OMIT==phase_control)
		{
			if (!snmp_parse_oid(MIB_PHASE_OMIT, anOID, &anOID_len))
			{
				snmp_perror(MIB_PHASE_OMIT);
				failures++;
			 }
			sprintf(tmp_log,"Send command to ASC controller: Phase omit control!\n");
			 std::cout <<tmp_log;
			 outputlog(tmp_log);

		}


	//snmp_add_var() return 0 if success
	if (snmp_add_var(pdu, anOID, anOID_len,'i', tmp_int))
	{
        snmp_perror(MIB_PHASE_HOLD);
		failures++;
	}



	if (failures)
	{
		snmp_close(ss);
		SOCK_CLEANUP;
		exit(1);
	}

		/*
		* Send the Request out.
		*/
		status = snmp_synch_response(ss, pdu, &response);

		/*
		* Process the response.
		*/
		if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR)
		{
			/*
			* SUCCESS: Print the result variables
			*/
			int *out = new int[MAX_ITEMS];
			int i =0;
			for(vars = response->variables; vars; vars = vars->next_variable)
				print_variable(vars->name, vars->name_length, vars);

			/* manipuate the information ourselves */
			for(vars = response->variables; vars; vars = vars->next_variable)
			{
				if (vars->type == ASN_OCTET_STR)
				{
					char *sp = (char *)malloc(1 + vars->val_len);
					memcpy(sp, vars->val.string, vars->val_len);
					sp[vars->val_len] = '\0';
					printf("value #%d is a string: %s\n", count++, sp);
					free(sp);
				}
				else
				{
					int *aa;
					aa =(int *)vars->val.integer;
					out[i++] = * aa;

					printf("value #%d is NOT a string! Ack!\n", count++);


				}

			}


		} else {
			/*
			* FAILURE: print what went wrong!
			*/

			if (status == STAT_SUCCESS)
				fprintf(stderr, "Error in packet\nReason: %s\n",
				snmp_errstring(response->errstat));
			else if (status == STAT_TIMEOUT)
				fprintf(stderr, "Timeout: No response from %s.\n",
				session.peername);
			else
				snmp_sess_perror("snmpdemoapp", ss);

		}

		/*
		* Clean up:
		*  1) free the response.
		*  2) close the session.
		*/
		if (response)
			snmp_free_pdu(response);
		snmp_close(ss);

		SOCK_CLEANUP;





}

void IntersectionPhaseRead()
{

	netsnmp_session session, *ss;
			netsnmp_pdu *pdu;
			netsnmp_pdu *response;

			oid anOID[MAX_OID_LEN];
			size_t anOID_len;

			netsnmp_variable_list *vars;
			int status;
			int count=1;



			/*
			* Initialize the SNMP library
			*/
			init_snmp("RSU");

			/*
			* Initialize a "session" that defines who we're going to talk to
			*/
			snmp_sess_init( &session );                   /* set up defaults */
			//char *ip = m_rampmeterip.GetBuffer(m_rampmeterip.GetLength());
			//char *port = m_rampmeterport.GetBuffer(m_rampmeterport.GetLength());
			char ipwithport[64];
			strcpy(ipwithport,INTip);
			//strcat(ipwithport,":");
			//strcat(ipwithport,INTport); //for ASC get status, DO NOT USE port!!!
			session.peername = strdup(ipwithport);
			/* set the SNMP version number */
			session.version = SNMP_VERSION_2c; //for ASC intersection
			//session.version = SNMP_VERSION_1; //for Rampmeter

			/* set the SNMPv1 community name used for authentication */
			session.community = (u_char *)"public";
			session.community_len = strlen((const char *)session.community);

			SOCK_STARTUP;
			ss = snmp_open(&session);                     /* establish the session */

			if (!ss)
			{
				snmp_sess_perror("RSU", &session);
				SOCK_CLEANUP;
				exit(1);
			}

			/*
			* Create the PDU for the data for our request.
			*   1) We're going to GET the system.sysDescr.0 node.
			*/
			pdu = snmp_pdu_create(SNMP_MSG_GET);
			anOID_len = MAX_OID_LEN;
			//for INTERSECTION CONTROLLER

			if (!snmp_parse_oid(RED_GROUP, anOID, &anOID_len)) //get RED group
			{
				snmp_perror(RED_GROUP);
				SOCK_CLEANUP;
				exit(1);
			}
			snmp_add_null_var(pdu, anOID, anOID_len);

			if (!snmp_parse_oid(YELLOW_GROUP, anOID, &anOID_len)) //get Yellow group
			{
				snmp_perror(YELLOW_GROUP);
				SOCK_CLEANUP;
				exit(1);
			}
			snmp_add_null_var(pdu, anOID, anOID_len);

			if (!snmp_parse_oid(GREEN_GROUP, anOID, &anOID_len)) //get Green group
			{
				snmp_perror(GREEN_GROUP);
				SOCK_CLEANUP;
				exit(1);
			}
			snmp_add_null_var(pdu, anOID, anOID_len);

			/*
			* Send the Request out.
			*/
			status = snmp_synch_response(ss, pdu, &response);

			/*
			* Process the response.
			*/
			if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR)
			{
				/*
				* SUCCESS: Print the result variables
				*/
				int *out = new int[MAX_ITEMS];
				int i =0;
				for(vars = response->variables; vars; vars = vars->next_variable)
					print_variable(vars->name, vars->name_length, vars);

				/* manipuate the information ourselves */
				for(vars = response->variables; vars; vars = vars->next_variable)
				{
					if (vars->type == ASN_OCTET_STR)
					{
						char *sp = (char *)malloc(1 + vars->val_len);
						memcpy(sp, vars->val.string, vars->val_len);
						sp[vars->val_len] = '\0';
						printf("value #%d is a string: %s\n", count++, sp);
						free(sp);
					}
					else
					{

						int *aa;
						aa =(int *)vars->val.integer;
						out[i++] = * aa;

						printf("value #%d is NOT a string! Ack!. Value = %d \n", count++,*aa);


					}

				}
				//FOR ASC INTERSECTIONS_ Draw the lights
						UpdateIntersectionStatus(out[0],out[1],out[2]);
				//For RAMP METER
				//set ramp meter status
						//SetRampMeterStatus(out);



			} else {
				/*
				* FAILURE: print what went wrong!
				*/

				if (status == STAT_SUCCESS)
					fprintf(stderr, "Error in packet\nReason: %s\n",
					snmp_errstring(response->errstat));
				else if (status == STAT_TIMEOUT)
					fprintf(stderr, "Timeout: No response from %s.\n",
					session.peername);
				else
					snmp_sess_perror("snmpdemoapp", ss);

			}

			/*
			* Clean up:
			*  1) free the response.
			*  2) close the session.
			*/
			if (response)
				snmp_free_pdu(response);
			snmp_close(ss);

		SOCK_CLEANUP;


}


void UpdateIntersectionStatus(int red, int yellow, int green)
{
		char *sz_temp;
		char sz_red[16];
		char sz_yellow[16];
		char sz_green[16];
		printf("red:%d, yellow:%d, green:%d \n",red,yellow,green);
		sz_temp = getBufferAsBinaryString(&red);
		strcpy(sz_red,sz_temp);
		//memcpy(sz_red,sz_temp,strlen(sz_temp));

		printf("Red binary string:%s\n",sz_red);

		sz_temp=getBufferAsBinaryString(&yellow);
		strcpy(sz_yellow,sz_temp);
		//memcpy(sz_yellow,sz_temp,strlen(sz_temp));
		printf("Yellow binary string:%s\n",sz_temp);

		sz_temp=getBufferAsBinaryString(&green);
		strcpy(sz_green,sz_temp);
		//memcpy(sz_green,sz_temp,strlen(sz_temp));
		printf("Green binary string:%s\n",sz_temp);

		for(int i = numPhases - 1; i >= 0; i--)
			{
				bool isRed = false;
				bool isYellow = false;
				bool isGreen = false;

				if(sz_red[i] == '1')
				{
					isRed = true;
				}
				if(sz_yellow[i] == '1')
				{
					isYellow = true;
				}
				if(sz_green[i] == '1')
				{
					isGreen = true;
				}

				vehiclePhases[numPhases - 1 - i].isRed = isRed;
				vehiclePhases[numPhases - 1 - i].isYellow = isYellow;
				vehiclePhases[numPhases - 1 - i].isGreen = isGreen;

			}
		  //Northbound 5   Northleft 0
		  //Southbound 1   Southleft 4
		  //Eastbound 7    Eastleft  2
		  //Westbound 3	   Westleft  6
}

void PrintPhases()
{
	char tmp_log[64];
	int tmp_red = 0;
	int tmp_green = 0;
	int tmp_yellow = 0;
	for(int i =0; i <numPhases; i++)
	{
		if (vehiclePhases[i].isRed) tmp_red = 1;
		else tmp_red = 0;

		if (vehiclePhases[i].isYellow) tmp_yellow = 1;
		else tmp_yellow = 0;

		if (vehiclePhases[i].isGreen) tmp_green = 1;
		else tmp_green = 0;

		sprintf(tmp_log,"Phase %d. green:%d. red:%d. yellow:%d.\n",i+1,tmp_green,tmp_red,tmp_yellow);
		std::cout <<tmp_log;
		outputlog(tmp_log);

	}



}

void IntersectionPreempt(int NO, bool ON)
{
	    netsnmp_session session, *ss;
		netsnmp_pdu *pdu;
		netsnmp_pdu *response;

		oid anOID[MAX_OID_LEN];
		size_t anOID_len;

		netsnmp_variable_list *vars;
		int status;
		int count=1;
		int  failures = 0;

		/*
		* Initialize the SNMP library
		*/
		init_snmp("RSU");

		/*
		* Initialize a "session" that defines who we're going to talk to
		*/
		snmp_sess_init( &session );                   /* set up defaults */

		char ipwithport[64];
		strcpy(ipwithport,INTip);
		strcat(ipwithport,":");
		strcat(ipwithport,INTport);
		session.peername = strdup(ipwithport);

		/* set the SNMP version number */
		session.version = SNMP_VERSION_2c;

		/* set the SNMPv1 community name used for authentication */
		session.community = (u_char *)"public";
		session.community_len = strlen((const char *)session.community);

		SOCK_STARTUP;
		ss = snmp_open(&session);                     /* establish the session */

		if (!ss)
		{
			snmp_sess_perror("RSU", &session);
			SOCK_CLEANUP;
			exit(1);
		}

		/*
		* Create the PDU for the data for our request.
		*   1) We're going to SET the system.sysDescr.0 node.
		*/
		pdu = snmp_pdu_create(SNMP_MSG_SET);
		anOID_len = MAX_OID_LEN;
		if (NO==1)
		{
			if (!snmp_parse_oid(PREEMPTOR1, anOID, &anOID_len))
			{
				snmp_perror(PREEMPTOR1);
				failures++;
			 }

		}
		else if (NO==2)
		{
			if (!snmp_parse_oid(PREEMPTOR2, anOID, &anOID_len))
			{
				snmp_perror(PREEMPTOR2);
				failures++;
			 }

		}
		else if (NO==3)
		{
			if (!snmp_parse_oid(PREEMPTOR3, anOID, &anOID_len))
			{
				snmp_perror(PREEMPTOR3);
				failures++;
			 }


		}
		else if (NO==4)
		{
			if (!snmp_parse_oid(PREEMPTOR4, anOID, &anOID_len))
			{
				snmp_perror(PREEMPTOR4);
				failures++;
			 }


		}

	//snmp_add_var() return 0 if success
	if (ON)
	{
		if (snmp_add_var(pdu, anOID, anOID_len,'i', "1"))
		{
            snmp_perror(PREEMPTOR3);
			failures++;
		}

	}
	else
	{
		if (snmp_add_var(pdu, anOID, anOID_len,'i', "0"))
		{
            snmp_perror(PREEMPTOR3);
			failures++;
		}

	}
	if (failures)
	{
		snmp_close(ss);
		SOCK_CLEANUP;
		exit(1);
	}

		/*
		* Send the Request out.
		*/
		status = snmp_synch_response(ss, pdu, &response);

		/*
		* Process the response.
		*/
		if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR)
		{
			/*
			* SUCCESS: Print the result variables
			*/
			int *out = new int[MAX_ITEMS];
			int i =0;
			for(vars = response->variables; vars; vars = vars->next_variable)
				print_variable(vars->name, vars->name_length, vars);

			/* manipuate the information ourselves */
			for(vars = response->variables; vars; vars = vars->next_variable)
			{
				if (vars->type == ASN_OCTET_STR)
				{
					char *sp = (char *)malloc(1 + vars->val_len);
					memcpy(sp, vars->val.string, vars->val_len);
					sp[vars->val_len] = '\0';
					printf("value #%d is a string: %s\n", count++, sp);
					free(sp);
				}
				else
				{
					int *aa;
					aa =(int *)vars->val.integer;
					out[i++] = * aa;

					printf("value #%d is NOT a string! Ack!\n", count++);


				}

			}


		} else {
			/*
			* FAILURE: print what went wrong!
			*/

			if (status == STAT_SUCCESS)
				fprintf(stderr, "Error in packet\nReason: %s\n",
				snmp_errstring(response->errstat));
			else if (status == STAT_TIMEOUT)
				fprintf(stderr, "Timeout: No response from %s.\n",
				session.peername);
			else
				snmp_sess_perror("snmpdemoapp", ss);

		}

		/*
		* Clean up:
		*  1) free the response.
		*  2) close the session.
		*/
		if (response)
			snmp_free_pdu(response);
		snmp_close(ss);

		SOCK_CLEANUP;

}








